package mysupertux.openGL;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.lwjgl.LWJGLException;
import org.lwjgl.input.Keyboard;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GL11;
import org.lwjgl.util.glu.GLU;

/**
 * Utils for initializing and working with OpenGL.
 */
public class OpenGLUtils {
	private static Log log = LogFactory.getLog(OpenGLUtils.class);

	/**
	 * Initializes fullscreen mode with the given width and heigt.
	 * 
	 * @param title
	 *            window title
	 */
	public static void initFullscreen(String title) {
		// set display mode and create fullscreen window
		try {
			// find displaymode
			switchMode();
			// start of in windowed mode
			Display.create();

			log.debug("Created OpenGL.");
		} catch (Exception e) {
			log.error("Failed to create OpenGL due to " + e);
			System.exit(1);
		}

		try {
			Keyboard.create();
		} catch (Exception e) {
			log.error("Failed to create Keybourd due to " + e);
			System.exit(1);
		}

		// enable texture mapping
		GL11.glEnable(GL11.GL_TEXTURE_2D);

		// alpha test/ blending
		GL11.glAlphaFunc(GL11.GL_GREATER, 0.5f);
		GL11.glEnable(GL11.GL_ALPHA_TEST);
		GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
		GL11.glEnable(GL11.GL_BLEND);

		GL11.glDisable(GL11.GL_DEPTH_TEST);

		// set up 2D mode
		GL11.glMatrixMode(GL11.GL_PROJECTION);
		GL11.glLoadIdentity();
		GLU.gluOrtho2D(0, Display.getDisplayMode().getWidth(), Display.getDisplayMode().getHeight(), 0);
		GL11.glMatrixMode(GL11.GL_MODELVIEW);
		GL11.glLoadIdentity();
		GL11.glViewport(0, 0, Display.getDisplayMode().getWidth(), Display.getDisplayMode().getHeight());
		// set clear color to black
		GL11.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
		// sync frame (only works on windows)
		Display.setVSyncEnabled(true);
	}

	/**
	 * Destroys the OpenGL window and frees all resources.
	 */
	public static void destroy() {
		Keyboard.destroy();
		Display.destroy();
	}

	/**
	 * Returns true if the window should be closed.
	 * 
	 * @return true if the window should be closed
	 */
	public static boolean isCloseRequested() {
		return Display.isCloseRequested();
	}

	private static void switchMode() throws LWJGLException {
		/** 800*600 */
		DisplayMode mode = findDisplayMode(800, 600, Display.getDisplayMode().getBitsPerPixel());
		Display.setDisplayModeAndFullscreen(mode);
	}

	/**
	 * Retrieves a displaymode, if one such is available
	 * 
	 * @param width
	 *            Required width
	 * @param height
	 *            Required height
	 * @param bpp
	 *            Minimum required bits per pixel
	 * @return
	 */
	private static DisplayMode findDisplayMode(int width, int height, int bpp) throws LWJGLException {
		DisplayMode[] modes = Display.getAvailableDisplayModes();
		for (DisplayMode mode : modes) {
			if (mode.getWidth() == width && mode.getHeight() == height && mode.getBitsPerPixel() >= bpp && mode.getFrequency() <= 60) {
				return mode;
			}
		}
		return Display.getDesktopDisplayMode();
	}
}
